---
sidebar_position: 1
---

# Get Started

The following document shows how React Complex Tree can be installed and used in your
web projects.


:::tip Headless Tree is available!

The successor for react-complex-tree, [Headless Tree](https://headless-tree.lukasbach.com/), is now available as Beta!

Headless Tree provides easier-to-use interfaces,
better customizability and more features.
Join [the Discord](https://discord.gg/KuZ6EezzVw) to get involved, and
[follow on Bluesky](https://bsky.app/profile/lukasbach.bsky.social) to
stay up to date.


:::

## Installation

To start using React Complex Table, install it to your project as a dependency via

```
npm install react-complex-tree
```

or

```
yarn add react-complex-tree
```

## Importing

You can always import any of the entities used in the examples directly as named imports from
the `react-complex-tree` package.

```typescript
import { UncontrolledTreeEnvironment, Tree, StaticTreeDataProvider } from 'react-complex-tree';
```

Make sure to also import the CSS file that defines the default styling of React Complex Tree, if
you do not intent do provide manual CSS declarations. More on the default stylings and possibilities
to modify those are given [in the guide on styling customizability](/docs/guides/styling). Import the
CSS in one of the following ways:

- Import it directly in your JS code, if you use Webpack with a loader that can load CSS files:
  ```js
  import 'react-complex-tree/lib/style-modern.css';
  ```
- Import it from within a CSS file with node-style package resolution:
  ```css
  @import '~react-complex-tree/lib/style-modern.css';
  ```
- Import it in your HTML by linking to the CSS file in your `node_modules` or on unpkg:
  ```html
  <head>
    <link href="https://unpkg.com/react-complex-tree/lib/style-modern.css" rel="stylesheet" />
  </head>
  ```

:::info

This will use the new styles introduced in v2.0.3.
If you want the old default styles, import `.../style.css` instead of `.../style-modern.css`.

:::

React Complex Tree comes compiled as CommonJS package, ESM package and ESNext package.

## Using CDNs

The package is also available as UMD bundle which can be consumed from the [unpkg CDN](https://unpkg.com).
You can import it in your HTML by copying the following snippet:

```html
<head>
  <link href="https://unpkg.com/react-complex-tree/lib/style.css" rel="stylesheet" />
  <script src="https://unpkg.com/react-complex-tree/lib/bundle.js"></script>
</head>
```

Importing the file `https://unpkg.com/react-complex-tree/lib/bundle.js` will make the variable `ReactComplexTree`
available to the global scope. All exports from the package are then available as children of that variable,
i.e. `ReactComplexTree.UncontrolledTreeEnvironment` can be used to reference the react component of an uncontrolled
tree environment.

## Integrating React Complex Tree into your project

After installation, import the package and start using it by creating a new tree environment that
contains a tree instance.

```jsx live
function App() {
  return (
    <UncontrolledTreeEnvironment
      dataProvider={new StaticTreeDataProvider(longTree.items, (item, data) => ({ ...item, data }))}
      getItemTitle={item => item.data}
      viewState={{}}
    >
      <Tree treeId="tree-1" rootItem="root" treeLabel="Tree Example" />
    </UncontrolledTreeEnvironment>
  );
}
```

The example above uses an [UncontrolledTreeEnvironment](/docs/react/UncontrolledTreeEnvironment), which is
the easiest way to get started as it maintains the tree view state in itself. Inside the environment,
the [Tree](/docs/react/Tree) itself is added to the DOM structure. You can add multiple trees within one
environment, that share a common state. Each tree needs to provide

- An individual ID for the tree, which remains unique for that tree.
- Which item is used as root item for that tree. Different trees may show different items as root.
- Optionally, a label, which is used as accessibility label for that tree to describe it to screen readers.

Individual trees do not provide their own state, but share the state that is provided by the environment.

For the environment, there are three ways to implement your tree environment:

- Use an [UncontrolledTreeEnvironment](/docs/react/UncontrolledTreeEnvironment) and a
  [StaticTreeDataProvider](/docs/api/classes/StaticTreeDataProvider) that provides the items. This is the easiest
  approach and is described below, and in the [static tree data provider guide](/docs/guides/static-data-provider).
- Use an [UncontrolledTreeEnvironment](/docs/react/UncontrolledTreeEnvironment) and implement a custom
  [TreeDataProvider](/docs/api/interfaces/TreeDataProvider). This is similarly easy and provides the ability to
  directly react to change events and define a lazy item-loading strategy. This approach is most likely the best
  way to integrate React Complex Tree in realistic scenarios. This approach is described [here](/docs/guides/uncontrolled-environment),
  with additional details on implementing custom a TreeDataProvider [here](/docs/guides/custom-data-provider).
- Use an [ControlledTreeEnvironment](/docs/react/ControlledTreeEnvironment). This requires you to define your
  own logic to manage the view state, thus requiring the most effort, but also provides the most customizability.
  This approach is described [here](/docs/guides/controlled-environment).

## Providing the data for the tree

:::info
There is another guide specifically for using static tree data providers [here](/docs/guides/static-data-provider),
which goes a bit more into detail.
:::

When integrating React Complex Tree with an uncontrolled environment and a static tree data provider, items
must be provided as [explicit data source](/docs/api/interfaces/ExplicitDataSource). An example for such
items looks like this:

```typescript jsx
const items = {
  root: {
    index: 'root',
    canMove: true,
    isFolder: true,
    children: ['child1', 'child2'],
    data: 'Root item',
    canRename: true,
  },
  child1: {
    index: 'child1',
    canMove: true,
    isFolder: false,
    children: [],
    data: 'Child item 1',
    canRename: true,
  },
  child2: {
    index: 'child2',
    canMove: true,
    isFolder: false,
    children: [],
    data: 'Child item 2',
    canRename: true,
  },
};
```

Each item needs to implement the [TreeItem](/docs/api/interfaces/TreeItem) interface. The `data` attribute
is generic and can contain any kind of data such as objects or strings. The environment then also needs to
implement the `getItemTitle` method, which derives the title of the item given a [TreeItem](/docs/api/interfaces/TreeItem)
instance. In our example, where `data` is just a string that contains the title, we can use the trivial
implementation of `getItemTitle={item => item.data}`.

We then create a new `StaticTreeDataProvider` instance that uses this data structure as data source. See the
[public interface](/docs/api/classes/StaticTreeDataProvider) of the `StaticTreeDataProvider` to get details on its constructor and abilities.

```typescript jsx
const dataProvider = new StaticTreeDataProvider(items, (item, newName) => ({ ...item, data: newName }));
```

The first constructor parameter is a record specifying available items. The second is an optional callback with which
you can customize how renaming an item works. It is called when the user renames an item (by using the F2 hotkey),
and how the item data payload is changed by that rename operation. This is necessary since react-complex-tree does not
by itself know which part of the item payload contains the name. This parameter has the type `(item: TreeItem<T>, newName: string) => TreeItem<T>`.

:::tip Handling drag events

To handle drag events, call `dataProvider.onDidChangeTreeData` like that:

```typescript
const listener = (changedItemIds: (string | number)[]) => {
  const changedItems = changedItemIds.map(dataProvider.getTreeItem)
  console.log("Changed items:", changedItems)
}
dataProvider.onDidChangeTreeData(listener)
```

You also need to set the property `canDragAndDrop` and either `canDropOnFolder` or `canReorderItems` on the tree environment.

:::

Finally, you can mount a `Tree` component within an `UncontrolledTreeEnvironment` that uses your dataProvider
as data source.

```jsx live
function App() {
  const items = {
    root: {
      index: 'root',
      isFolder: true,
      children: ['child1', 'child2'],
      data: 'Root item',
    },
    child1: {
      index: 'child1',
      children: [],
      data: 'Child item 1',
    },
    child2: {
      index: 'child2',
      isFolder: true,
      children: ['child3'],
      data: 'Child item 2',
    },
    child3: {
      index: 'child3',
      children: [],
      data: 'Child item 3',
    },
  };

  const dataProvider = new StaticTreeDataProvider(items, (item, newName) => ({ ...item, data: newName }));

  return (
    <UncontrolledTreeEnvironment
      dataProvider={dataProvider}
      getItemTitle={item => item.data}
      viewState={{}}
      canDragAndDrop={true}
      canDropOnFolder={true}
      canReorderItems={true}
    >
      <Tree treeId="tree-2" rootItem="root" treeLabel="Tree Example" />
    </UncontrolledTreeEnvironment>
  );
}
```